package com.zx.idc.backend.gui.ins.service;

import com.rxliuli.rxeasyexcel.domain.ExcelImportError;
import com.rxliuli.rxeasyexcel.domain.ImportDomain;
import com.zx.idc.backend.gui.scheduler.ins.filtermonitorlog.service.FilterInstructionJobService;
import com.zx.idc.common.constants.InsCacheStatus;
import com.zx.idc.common.exception.*;
import com.zx.idc.common.lang.BeanUtil;
import com.zx.idc.ds.base.house.entity.BaseHouseInfo;
import com.zx.idc.ds.base.house.service.IBaseHouseInfoService;
import com.zx.idc.ds.ins.entity.InsFilterArchive;
import com.zx.idc.ds.ins.service.IInsFilterArchiveService;
import com.zx.idc.ds.ins.service.IInsFilterRuleService;
import com.zx.idc.ds.ins.service.IInsFilterService;
import com.zx.idc.ds.ins.vo.InsFilterVo;
import com.zx.idc.ds.sys.service.ISysGlobalStatusService;
import com.zx.idc.internal.exception.SendMessageException;
import com.zx.idc.internal.ins.InstructionCallResult;
import com.zx.idc.internal.service.SMMSFilterInstructionService;
import com.zx.idc.qc.exception.JobExistsException;
import com.zx.idc.qc.exception.QuartzJobException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Transactional(readOnly = false, rollbackFor = Exception.class)
public class InsFilterInterfaceService {
    private static final Logger LOG = LoggerFactory.getLogger(InsFilterInterfaceService.class);

    private static final String ADD_TYPE = "0";
    private static final Integer SUCCESS = 200;

    @Autowired
    private IInsFilterService iInsFilterService;
    @Autowired
    private IInsFilterArchiveService iInsFilterArchiveService;

    @Autowired
    private IBaseHouseInfoService iBaseHouseInfoService;

    @Autowired
    private SMMSFilterInstructionService smmsFilterInstructionService;

    @Autowired
    private FilterInstructionJobService filterInstructionJobService;

    @Autowired
    private ISysGlobalStatusService iSysGlobalStatusService;

    @Autowired
    private IInsFilterRuleService iInsFilterRuleService;



    public Boolean add(InsFilterVo insFilterVo) throws EncryptException, JobExistsException, QuartzJobException, SendMessageException, CallInternalInterfaceException {
        if (Duration.between(insFilterVo.getExpiredTime(), LocalDateTime.now()).getSeconds() > 0) {
            throw new GlobalException("过期时间已过，无法添加过滤指令");
        }
        Boolean flag = iInsFilterService.add(insFilterVo);
        if (!flag)
            return false;

        //插入一个副本到存档表
        InsFilterArchive insFilterArchive = new InsFilterArchive();
        BeanUtils.copyProperties(insFilterVo, insFilterArchive);
        iInsFilterArchiveService.insert(insFilterArchive);

        //生效时间小于当前时间
        if (Duration.between(insFilterVo.getEffectTime(), LocalDateTime.now()).getSeconds() > 0) {
            //直接调用
            for (String houseId : insFilterVo.getHouseId().split(",")) {
                InstructionCallResult result = smmsFilterInstructionService.addRules(insFilterVo, houseId);
                if (result == null || result.getCode() != 200) {
                    LOG.warn("send addition filter instruction to filter server fail, command id: {}", insFilterVo.getId());
                }
            }
            LOG.info("添加过滤规则成功，命令id：{}", insFilterVo.getId());
            //添加删除规则定时任务
            filterInstructionJobService.generateDeleteScheduler(insFilterVo.getId());
            cleanInsCache(insFilterVo);
            return true;
        }
        //添加定时任务
        filterInstructionJobService.generateScheduler(insFilterVo.getId());
        //批量修改指令添加清除缓存状态
        cleanInsCache(insFilterVo);
        return true;
    }

    private void cleanInsCache(InsFilterVo insFilterVo) {
        List<Long> ids = Arrays.stream(insFilterVo.getHouseId().split(","))
            .map(Long::valueOf)
            .collect(Collectors.toList());
        iSysGlobalStatusService.updateInsStatusByHouseIds(ids, InsCacheStatus.ClEAN_CACHE_NEED);
    }

    public Boolean updateInsFilter(InsFilterVo insFilterVo) throws EncryptException, QuartzJobException, SendMessageException, JobExistsException {
        if (Duration.between(insFilterVo.getEffectTime(), LocalDateTime.now()).getSeconds() >= 0) {
            throw new InstructionUpdateTimeOutException("生效时间已过,不能修改");
        }
        if (Duration.between(insFilterVo.getExpiredTime(), LocalDateTime.now()).getSeconds() > 0) {
            throw new GlobalException("过期时间已过，过滤指令已作废");
        }
        InsFilterVo insFilterOld = iInsFilterService.updateInsFilter(insFilterVo);
        if (insFilterOld == null)
            return false;

        //更新一个副本到存档表
        InsFilterArchive insFilterArchive = new InsFilterArchive();
        BeanUtils.copyProperties(insFilterVo, insFilterArchive);
        iInsFilterArchiveService.updateById(insFilterArchive);

        //删除任务
        filterInstructionJobService.deleteScheduler(insFilterOld.getId());
        //添加任务
        filterInstructionJobService.generateScheduler(insFilterOld.getId());
        cleanInsCache(insFilterVo);
        return true;
    }

    public ImportDomain<InsFilterVo> importData(List<InsFilterVo> data, Map<String, Integer> columnInfoMap) throws EncryptException, JobExistsException, QuartzJobException, SendMessageException {
        ImportDomain<InsFilterVo> insFilterVoImportDomain;
        try {
            insFilterVoImportDomain = iInsFilterService.insertImportData(data, columnInfoMap);
        } catch (ExcelImportErrorException e) {
            throw e;
        }
        List<ExcelImportError> errors = insFilterVoImportDomain.getErrors();
        //有错误数据直接返回
        if (errors != null && !errors.isEmpty()) {
            return insFilterVoImportDomain;
        }
        //添加任务 拦截器接口
        List<InsFilterVo> importDomainData = insFilterVoImportDomain.getData();
        if (importDomainData != null && !importDomainData.isEmpty()) {
            for (InsFilterVo datum : importDomainData) {
                filterInstructionJobService.generateScheduler(datum.getId());
            }
        }
        List<Long> ids = iBaseHouseInfoService.selectListReturnId();
        iSysGlobalStatusService.updateInsStatusByHouseIds(ids, InsCacheStatus.ClEAN_CACHE_NEED);
        return insFilterVoImportDomain;
    }

    public void deleteInsFilter(InsFilterVo insFilterVo) throws EncryptException, SendMessageException, QuartzJobException, CallInternalInterfaceException {
        //调用删除服务接口
        filterInstructionJobService.deleteScheduler(insFilterVo.getId());
        iInsFilterService.deleteById(insFilterVo.getId());
        Map<String, Object> columnMap = new HashMap<>();
        columnMap.put("insId", insFilterVo.getId());
        iInsFilterRuleService.deleteByMap(columnMap);
        for (String houseId : insFilterVo.getHouseId().split(",")) {
            InstructionCallResult result = smmsFilterInstructionService.delRules(insFilterVo, houseId);
            if (!SUCCESS.equals(result.getCode())) {
                LOG.warn("send deletion filter instruction to filter server fail, command id: {}, houseId: {}, response code: {}, response message: {}",
                    insFilterVo.getId(), houseId, result.getCode(), result.getComments());
            }
        }
    }
}
